package com.cencat.driver.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.driver.entity.DeliveryTask;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 配送任务数据访问层接口
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Repository
@Mapper
public interface DeliveryTaskMapper extends BaseMapper<DeliveryTask> {

    /**
     * 根据任务编号查询配送任务
     * 
     * @param taskCode 任务编号
     * @param tenantId 租户ID
     * @return 配送任务
     */
    @Select("SELECT * FROM delivery_task WHERE task_code = #{taskCode} AND tenant_id = #{tenantId} AND deleted = 0")
    DeliveryTask selectByTaskCode(@Param("taskCode") String taskCode, @Param("tenantId") Long tenantId);

    /**
     * 根据司机ID查询配送任务列表
     * 
     * @param driverId 司机ID
     * @param tenantId 租户ID
     * @return 配送任务列表
     */
    @Select("SELECT * FROM delivery_task WHERE driver_id = #{driverId} AND tenant_id = #{tenantId} AND deleted = 0 ORDER BY create_time DESC")
    List<DeliveryTask> selectByDriverId(@Param("driverId") Long driverId, @Param("tenantId") Long tenantId);

    /**
     * 根据订单ID查询配送任务列表
     * 
     * @param orderId 订单ID
     * @param tenantId 租户ID
     * @return 配送任务列表
     */
    @Select("SELECT * FROM delivery_task WHERE order_id = #{orderId} AND tenant_id = #{tenantId} AND deleted = 0 ORDER BY create_time DESC")
    List<DeliveryTask> selectByOrderId(@Param("orderId") Long orderId, @Param("tenantId") Long tenantId);

    /**
     * 根据任务状态查询配送任务列表
     * 
     * @param status 任务状态
     * @param tenantId 租户ID
     * @return 配送任务列表
     */
    @Select("SELECT * FROM delivery_task WHERE status = #{status} AND tenant_id = #{tenantId} AND deleted = 0 ORDER BY create_time DESC")
    List<DeliveryTask> selectByStatus(@Param("status") Integer status, @Param("tenantId") Long tenantId);

    /**
     * 根据优先级查询配送任务列表
     * 
     * @param priority 优先级
     * @param tenantId 租户ID
     * @return 配送任务列表
     */
    @Select("SELECT * FROM delivery_task WHERE priority = #{priority} AND tenant_id = #{tenantId} AND deleted = 0 ORDER BY create_time DESC")
    List<DeliveryTask> selectByPriority(@Param("priority") Integer priority, @Param("tenantId") Long tenantId);

    /**
     * 查询司机的待处理任务列表
     * 
     * @param driverId 司机ID
     * @param tenantId 租户ID
     * @return 待处理任务列表
     */
    @Select("SELECT * FROM delivery_task WHERE driver_id = #{driverId} AND status IN (1, 2, 3) AND tenant_id = #{tenantId} AND deleted = 0 ORDER BY priority DESC, create_time ASC")
    List<DeliveryTask> selectPendingTasksByDriverId(@Param("driverId") Long driverId, @Param("tenantId") Long tenantId);

    /**
     * 查询未分配的任务列表
     * 
     * @param tenantId 租户ID
     * @return 未分配任务列表
     */
    @Select("SELECT * FROM delivery_task WHERE driver_id IS NULL AND status = 1 AND tenant_id = #{tenantId} AND deleted = 0 ORDER BY priority DESC, create_time ASC")
    List<DeliveryTask> selectUnassignedTasks(@Param("tenantId") Long tenantId);

    /**
     * 分页查询配送任务列表
     * 
     * @param page 分页参数
     * @param taskCode 任务编号（模糊查询）
     * @param driverId 司机ID
     * @param orderId 订单ID
     * @param status 任务状态
     * @param priority 优先级
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param tenantId 租户ID
     * @return 分页结果
     */
    @Select("<script>" +
            "SELECT * FROM delivery_task WHERE tenant_id = #{tenantId} AND deleted = 0" +
            "<if test='taskCode != null and taskCode != \"\">" +
            " AND task_code LIKE CONCAT('%', #{taskCode}, '%')" +
            "</if>" +
            "<if test='driverId != null'>" +
            " AND driver_id = #{driverId}" +
            "</if>" +
            "<if test='orderId != null'>" +
            " AND order_id = #{orderId}" +
            "</if>" +
            "<if test='status != null'>" +
            " AND status = #{status}" +
            "</if>" +
            "<if test='priority != null'>" +
            " AND priority = #{priority}" +
            "</if>" +
            "<if test='startTime != null'>" +
            " AND create_time >= #{startTime}" +
            "</if>" +
            "<if test='endTime != null'>" +
            " AND create_time <= #{endTime}" +
            "</if>" +
            " ORDER BY create_time DESC" +
            "</script>")
    IPage<DeliveryTask> selectPageWithConditions(Page<DeliveryTask> page,
                                               @Param("taskCode") String taskCode,
                                               @Param("driverId") Long driverId,
                                               @Param("orderId") Long orderId,
                                               @Param("status") Integer status,
                                               @Param("priority") Integer priority,
                                               @Param("startTime") LocalDateTime startTime,
                                               @Param("endTime") LocalDateTime endTime,
                                               @Param("tenantId") Long tenantId);

    /**
     * 统计配送任务数量
     * 
     * @param tenantId 租户ID
     * @return 任务总数
     */
    @Select("SELECT COUNT(*) FROM delivery_task WHERE tenant_id = #{tenantId} AND deleted = 0")
    Long countByTenantId(@Param("tenantId") Long tenantId);

    /**
     * 根据状态统计配送任务数量
     * 
     * @param status 任务状态
     * @param tenantId 租户ID
     * @return 任务数量
     */
    @Select("SELECT COUNT(*) FROM delivery_task WHERE status = #{status} AND tenant_id = #{tenantId} AND deleted = 0")
    Long countByStatus(@Param("status") Integer status, @Param("tenantId") Long tenantId);

    /**
     * 统计司机的任务数量
     * 
     * @param driverId 司机ID
     * @param tenantId 租户ID
     * @return 任务数量
     */
    @Select("SELECT COUNT(*) FROM delivery_task WHERE driver_id = #{driverId} AND tenant_id = #{tenantId} AND deleted = 0")
    Long countByDriverId(@Param("driverId") Long driverId, @Param("tenantId") Long tenantId);

    /**
     * 统计司机指定状态的任务数量
     * 
     * @param driverId 司机ID
     * @param status 任务状态
     * @param tenantId 租户ID
     * @return 任务数量
     */
    @Select("SELECT COUNT(*) FROM delivery_task WHERE driver_id = #{driverId} AND status = #{status} AND tenant_id = #{tenantId} AND deleted = 0")
    Long countByDriverIdAndStatus(@Param("driverId") Long driverId, @Param("status") Integer status, @Param("tenantId") Long tenantId);

    /**
     * 更新任务状态
     * 
     * @param id 任务ID
     * @param status 任务状态
     * @param tenantId 租户ID
     * @return 更新行数
     */
    @Update("UPDATE delivery_task SET status = #{status}, update_time = NOW() WHERE id = #{id} AND tenant_id = #{tenantId}")
    int updateStatus(@Param("id") Long id, @Param("status") Integer status, @Param("tenantId") Long tenantId);

    /**
     * 分配任务给司机
     * 
     * @param id 任务ID
     * @param driverId 司机ID
     * @param tenantId 租户ID
     * @return 更新行数
     */
    @Update("UPDATE delivery_task SET driver_id = #{driverId}, status = 2, assign_time = NOW(), update_time = NOW() WHERE id = #{id} AND tenant_id = #{tenantId}")
    int assignToDriver(@Param("id") Long id, @Param("driverId") Long driverId, @Param("tenantId") Long tenantId);

    /**
     * 司机接受任务
     * 
     * @param id 任务ID
     * @param driverId 司机ID
     * @param tenantId 租户ID
     * @return 更新行数
     */
    @Update("UPDATE delivery_task SET status = 3, accept_time = NOW(), update_time = NOW() WHERE id = #{id} AND driver_id = #{driverId} AND tenant_id = #{tenantId}")
    int acceptTask(@Param("id") Long id, @Param("driverId") Long driverId, @Param("tenantId") Long tenantId);

    /**
     * 司机拒绝任务
     * 
     * @param id 任务ID
     * @param driverId 司机ID
     * @param rejectReason 拒绝原因
     * @param tenantId 租户ID
     * @return 更新行数
     */
    @Update("UPDATE delivery_task SET status = 6, reject_reason = #{rejectReason}, reject_time = NOW(), update_time = NOW() WHERE id = #{id} AND driver_id = #{driverId} AND tenant_id = #{tenantId}")
    int rejectTask(@Param("id") Long id, @Param("driverId") Long driverId, @Param("rejectReason") String rejectReason, @Param("tenantId") Long tenantId);

    /**
     * 开始配送
     * 
     * @param id 任务ID
     * @param driverId 司机ID
     * @param tenantId 租户ID
     * @return 更新行数
     */
    @Update("UPDATE delivery_task SET status = 4, start_time = NOW(), update_time = NOW() WHERE id = #{id} AND driver_id = #{driverId} AND tenant_id = #{tenantId}")
    int startDelivery(@Param("id") Long id, @Param("driverId") Long driverId, @Param("tenantId") Long tenantId);

    /**
     * 完成配送
     * 
     * @param id 任务ID
     * @param driverId 司机ID
     * @param tenantId 租户ID
     * @return 更新行数
     */
    @Update("UPDATE delivery_task SET status = 5, complete_time = NOW(), update_time = NOW() WHERE id = #{id} AND driver_id = #{driverId} AND tenant_id = #{tenantId}")
    int completeDelivery(@Param("id") Long id, @Param("driverId") Long driverId, @Param("tenantId") Long tenantId);

    /**
     * 更新任务位置信息
     * 
     * @param id 任务ID
     * @param longitude 经度
     * @param latitude 纬度
     * @param address 地址
     * @param tenantId 租户ID
     * @return 更新行数
     */
    @Update("UPDATE delivery_task SET current_longitude = #{longitude}, current_latitude = #{latitude}, " +
            "current_address = #{address}, location_update_time = NOW(), update_time = NOW() " +
            "WHERE id = #{id} AND tenant_id = #{tenantId}")
    int updateLocation(@Param("id") Long id,
                      @Param("longitude") Double longitude,
                      @Param("latitude") Double latitude,
                      @Param("address") String address,
                      @Param("tenantId") Long tenantId);

    /**
     * 批量更新任务状态
     * 
     * @param ids 任务ID列表
     * @param status 任务状态
     * @param tenantId 租户ID
     * @return 更新行数
     */
    @Update("<script>" +
            "UPDATE delivery_task SET status = #{status}, update_time = NOW() WHERE tenant_id = #{tenantId} AND id IN" +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdateStatus(@Param("ids") List<Long> ids, @Param("status") Integer status, @Param("tenantId") Long tenantId);

    /**
     * 检查任务编号是否存在
     * 
     * @param taskCode 任务编号
     * @param excludeId 排除的任务ID（用于更新时检查）
     * @param tenantId 租户ID
     * @return 是否存在
     */
    @Select("<script>" +
            "SELECT COUNT(*) FROM delivery_task WHERE task_code = #{taskCode} AND tenant_id = #{tenantId} AND deleted = 0" +
            "<if test='excludeId != null'>" +
            " AND id != #{excludeId}" +
            "</if>" +
            "</script>")
    int existsByTaskCode(@Param("taskCode") String taskCode, @Param("excludeId") Long excludeId, @Param("tenantId") Long tenantId);

    /**
     * 查询超时未处理的任务
     * 
     * @param timeoutMinutes 超时分钟数
     * @param tenantId 租户ID
     * @return 超时任务列表
     */
    @Select("SELECT * FROM delivery_task WHERE status IN (1, 2) AND " +
            "TIMESTAMPDIFF(MINUTE, create_time, NOW()) > #{timeoutMinutes} " +
            "AND tenant_id = #{tenantId} AND deleted = 0 ORDER BY create_time ASC")
    List<DeliveryTask> selectTimeoutTasks(@Param("timeoutMinutes") Integer timeoutMinutes, @Param("tenantId") Long tenantId);

    /**
     * 查询今日任务统计
     * 
     * @param driverId 司机ID
     * @param tenantId 租户ID
     * @return 任务统计信息
     */
    @Select("SELECT " +
            "COUNT(*) as total_count, " +
            "SUM(CASE WHEN status = 5 THEN 1 ELSE 0 END) as completed_count, " +
            "SUM(CASE WHEN status IN (1, 2, 3, 4) THEN 1 ELSE 0 END) as pending_count, " +
            "SUM(CASE WHEN status = 6 THEN 1 ELSE 0 END) as rejected_count " +
            "FROM delivery_task WHERE driver_id = #{driverId} AND DATE(create_time) = CURDATE() " +
            "AND tenant_id = #{tenantId} AND deleted = 0")
    @MapKey("total_count")
    java.util.Map<String, Object> selectTodayStatistics(@Param("driverId") Long driverId, @Param("tenantId") Long tenantId);
}